package com.ideaaedi.commonspring.filter;

import com.ideaaedi.commonds.monitor.WatchTimeUtil;
import com.ideaaedi.commonspring.spi.TimeWatcherFilterReplacer;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.core.Ordered;

import javax.annotation.Nullable;
import java.io.IOException;

/**
 * 计时器进出口控制
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img
 * src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 2100.10.7.LTS17
 */
@Slf4j
public class TimeWatcherFilter implements Filter, InitializingBean, Ordered {
    
    public static final String BEAN_NAME = "timeWatcherFilter";
    
    private final int order;
    
    private final boolean prettyResult;
    
    private final ApplicationContext applicationContext;
    
    @Nullable
    private TimeWatcherFilterReplacer timeWatcherFilterReplacer;
    
    public TimeWatcherFilter(int order, boolean prettyResult, ApplicationContext applicationContext) {
        this.order = order;
        this.prettyResult = prettyResult;
        this.applicationContext = applicationContext;
    }
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
            ServletException {
        // 替换整个过滤器逻辑
        if (timeWatcherFilterReplacer != null && !timeWatcherFilterReplacer.replacePrint()) {
            timeWatcherFilterReplacer.doFilter(request, response, chain, prettyResult);
            return;
        }
        HttpServletRequest httpServletRequest = null;
        if (request instanceof HttpServletRequest) {
            httpServletRequest = (HttpServletRequest)request;
        }
        try {
            WatchTimeUtil.Manager.init();
            String requestUri = "";
            if (httpServletRequest != null) {
                requestUri = httpServletRequest.getRequestURI();
            }
            WatchTimeUtil.start("request-uri -> " + requestUri);
            chain.doFilter(request, response);
        } finally {
            try {
                WatchTimeUtil.stop();
                if (timeWatcherFilterReplacer != null) {
                    timeWatcherFilterReplacer.print(httpServletRequest, prettyResult);
                } else {
                    if (log.isInfoEnabled()) {
                        log.info("consume time -> {}", prettyResult ? WatchTimeUtil.prettyResult() : WatchTimeUtil.result());
                    }
                }
            } catch (Exception e) {
                log.warn("WatchTimeUtil.stop occur exception. e.getMessage() -> {}", e.getMessage());
            }
            WatchTimeUtil.Manager.clear();
        }
    }
    
    @Override
    public void afterPropertiesSet() throws Exception {
        timeWatcherFilterReplacer = applicationContext.getBeanProvider(TimeWatcherFilterReplacer.class)
                .getIfAvailable();
    }
    
    @Override
    public int getOrder() {
        return order;
    }
}